package com.bytz.modules.cms.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bytz.common.exception.BytzBootException;
import com.bytz.common.system.query.QueryGenerator;
import com.bytz.modules.cms.product.entity.Product;
import com.bytz.modules.cms.product.entity.ProductPack;
import com.bytz.modules.cms.product.entity.ProductPackDetail;
import com.bytz.modules.cms.product.model.ProductModel;
import com.bytz.modules.cms.product.model.ProductPackModel;
import com.bytz.modules.cms.product.service.IMallProductPackService;
import com.bytz.modules.cms.product.service.IMallProductService;
import com.bytz.modules.cms.product.service.IProductPackDetailService;
import com.bytz.modules.cms.product.service.IProductService;
import com.bytz.modules.cms.reseller.util.ResellerSecurityUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MallProductPackServiceImpl extends ProductPackServiceImpl implements IMallProductPackService {

    @Autowired
    private IMallProductService mallProductService;

    @Autowired
    private IProductService productService;

    @Autowired
    private IProductPackDetailService productPackDetailService;

    @Override
    public List<ProductPackModel> searchPack(String searchCondition) {

        String resellerId = ResellerSecurityUtils.getUserId();

        if (StringUtils.isBlank(searchCondition)) {
            return new ArrayList<>();
        }

        List<ProductPack> productPackList = lambdaQuery()
                .and(queryWrapper -> queryWrapper.eq(ProductPack::getResellerId, resellerId).or().isNull(ProductPack::getResellerId))
                .likeRight(ProductPack::getPackName, searchCondition)
                .last("LIMIT 10")
                .list();
        return BeanUtil.copyToList(productPackList, ProductPackModel.class);
    }

    @Override
    public ProductPackModel getPackDetail(String id) {

        ProductPack productPack = lambdaQuery().eq(ProductPack::getId, id).one();

        //获得该包id下的所有详情 然后取其商品ID
        List<String> productIds = detailService.getByPackId(productPack.getId())
                .stream()
                .map(ProductPackDetail::getProductId)
                .collect(Collectors.toList());

        ProductPackModel result = new ProductPackModel();
        BeanUtils.copyProperties(productPack, result);

        if (CollectionUtil.isEmpty(productIds)) {
            return result;
        }


        result.setProducts(mallProductService.getProductDetailByIds(productIds));
        return result;
    }

    @Override
    public IPage<ProductPackModel> queryPage(Page<ProductPack> productPackPage, ProductPackModel packModel, Map<String, String[]> parameterMap) {
        LambdaQueryWrapper<ProductPack> productPackLambdaQueryWrapper = QueryGenerator.initLambdaQueryWrapper(packModel, parameterMap, ProductPack.class);
        Page<ProductPackModel> productPackModelPage = new Page<>();
        //获取当前登录的经销商ID
        String reseller = ResellerSecurityUtils.getUserId();
        productPackLambdaQueryWrapper.and(and -> and
                .eq(packModel.getResellerOnly() == null || packModel.getResellerOnly(), ProductPack::getResellerId, reseller)
                .or().isNull(packModel.getResellerOnly() == null || !packModel.getResellerOnly(), ProductPack::getResellerId)
        ).orderByDesc(ProductPack::getUpdateTime);
        //此时得到了对应ResellerId，ProductPack
        this.page(productPackPage, productPackLambdaQueryWrapper);
        //判断是否记录为空
        if (productPackPage.getRecords().isEmpty()) {
            return productPackModelPage;
        }
        //进行对象拷贝，浅拷贝要忽略原来的records，不需要这个数据,因为records里面的属性都是ProductPack，我们需要的records里面应该装的是ProductPackModel
        BeanUtils.copyProperties(productPackPage, productPackModelPage, "records");

        List<ProductPack> productPackList = productPackPage.getRecords();
        List<ProductPackModel> productPackModelList = new ArrayList<>();
        //获取当前的包ID
        List<String> packIds = productPackList.stream()
                .map(ProductPack::getId)
                .collect(Collectors.toList());
        //获取所有的打包详情
        List<ProductPackDetail> productPackDetailList = productPackDetailService.getAllPackDetailByPackIds(packIds);
        //对打包详情数据分组
        Map<String, List<ProductPackDetail>> detailPackIdGroup = productPackDetailList.stream()
                .collect(Collectors.groupingBy(ProductPackDetail::getPackId));
        //获取对应的产品ID
        Set<String> productIds = productPackDetailList.stream()
                .map(ProductPackDetail::getProductId)
                .collect(Collectors.toSet());
        Map<String, ProductModel> productIdMap = mallProductService.getProductDetailByIds(productIds).stream()
                .collect(Collectors.toMap(ProductModel::getId, productModel -> productModel));
        productPackList.forEach(productPack -> {
            ProductPackModel productPackModel = new ProductPackModel();
            //再次使用对象拷贝
            BeanUtils.copyProperties(productPack, productPackModel);
            String packId = productPack.getId();
            //目标是向ProductPackModel对象赋值
            List<ProductPackDetail> productPackDetails = detailPackIdGroup.get(packId);
            if (productPackDetails == null) {
                productPackModel.setProductCount(0);
                productPackModel.setPriceCount(BigDecimal.ZERO);
                productPackModelList.add(productPackModel);
                return;
            }
            BigDecimal countPrice = BigDecimal.ZERO;
            for (ProductPackDetail detail : productPackDetails) {
                countPrice = countPrice.add(ObjectUtil.defaultIfNull(productIdMap.get(detail.getProductId()).getCalculatePrice(), BigDecimal.ZERO));
            }
            productPackModel.setProductCount(productPackDetails.size());
            productPackModel.setPriceCount(countPrice);
            productPackModelList.add(productPackModel);
        });
        productPackModelPage.setRecords(productPackModelList);
        return productPackModelPage;
    }


    @Transactional
    @Override
    public ProductPackModel updateProductPack(ProductPackModel productPackModel) {
        //先判断resellerId是不是一样，一样才能删除
        //获取当前登录的id
        String reseller = ResellerSecurityUtils.getUserId();
        if (!reseller.equals(productPackModel.getResellerId())) {
            throw new BytzBootException("数据有误，不可修改");
        }
        return this.getPackDetail(productPackModel.getId());
    }


    @Transactional
    @Override
    public Boolean deleteById(String id) {
        //先判断resellerId是不是一样，有才能删除
        //获取当前登录的id
        String reseller = ResellerSecurityUtils.getUserId();
        ProductPack productPack = this.getById(id);
        if (!reseller.equals(productPack.getResellerId())) {
            throw new BytzBootException("不可删除");
        }
        //先删除pack_detail表下的
        productPackDetailService.removeByPackId(id);
        //删除 pack 表下的
        return this.removeById(id);
    }


    @Transactional
    @Override
    public void createPack(ProductPack productPack) {
        String reseller = ResellerSecurityUtils.getUserId();
        boolean exists = lambdaQuery()
                .eq(ProductPack::getPackName, productPack.getPackName())
                .and(qw -> qw.isNull(ProductPack::getResellerId).or().eq(ProductPack::getResellerId, reseller))
                .exists();
        if (exists) {
            throw new BytzBootException("有重复包名，不可创建");
        }
        productPack.setResellerId(reseller);
        this.save(productPack);
    }

    @Transactional
    @Override
    public void createPackDetails(ProductPackModel productPackModel) {
        //获取包packId
        String packId = productPackModel.getId();
        updatePackName(productPackModel.getPackName(), packId);
        Set<String> dbProductIdSet = productPackDetailService.getByPackId(packId)
                .stream()
                .map(ProductPackDetail::getProductId)
                .collect(Collectors.toSet());
        //获取客户要打包的商品集合
        List<ProductModel> products = productPackModel.getProducts();
        List<String> productNumbers = products.stream()
                .map(ProductModel::getProductNumber)
                .collect(Collectors.toList());
        //通过PN码获得产品列表
        List<Product> productList = productService.getByProductNumbers(productNumbers);
        //获得要保存或编辑的产品id
        Set<String> importProductIdSet = productList.stream()
                .map(Product::getId)
                .collect(Collectors.toSet());
        Set<String> delIdSet = new HashSet<>(dbProductIdSet);
        //需要删除的包详情信息
        delIdSet.removeAll(importProductIdSet);
        if (!delIdSet.isEmpty()) {
            productPackDetailService.removeByProductIds(delIdSet, packId);
        }
        Set<String> addIdSet = new HashSet<>(importProductIdSet);
        addIdSet.removeAll(dbProductIdSet);
        if (!addIdSet.isEmpty()) {
            List<ProductPackDetail> productPackDetailList = addIdSet.stream().map(productId -> {
                ProductPackDetail productPackDetail = new ProductPackDetail();
                productPackDetail.setPackId(packId);
                productPackDetail.setProductId(productId);
                return productPackDetail;
            }).collect(Collectors.toList());
            productPackDetailService.saveBatch(productPackDetailList);
        }
    }

    @Override
    public ProductPackModel importProductPackDetail(List<String> productNumbers) {
        List<Product> productList = productService.getByProductNumbers(productNumbers);
        if (CollectionUtils.isEmpty(productList)) {
            throw new BytzBootException("导入的信息全部有误");
        }
        Set<String> hasProductNumbers = productList.stream()
                .map(Product::getProductNumber)
                .collect(Collectors.toSet());
        Set<String> noExist = new HashSet<>(productNumbers);
        noExist.removeAll(hasProductNumbers);
        if (!CollectionUtils.isEmpty(noExist)) {
            throw new BytzBootException("导入失败，该产品" + String.join(",", noExist) + "编码不存在");
        }
        List<String> productIds = productList
                .stream()
                .map(Product::getId)
                .collect(Collectors.toList());

        ProductPackModel result = new ProductPackModel();
        result.setProducts(mallProductService.getProductDetailByIds(productIds));
        return result;
    }


    /**
     * 更新 包名
     */
    private void updatePackName(String packName, String packId) {
        LambdaUpdateWrapper<ProductPack> productPackLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        productPackLambdaUpdateWrapper
                .set(ProductPack::getPackName, packName)
                .set(ProductPack::getUpdateTime, LocalDateTime.now())
                .eq(ProductPack::getId, packId);
        this.update(productPackLambdaUpdateWrapper);
    }
}
